<?php


namespace app\api\service;


use app\api\model\User as UserModel;
use app\lib\enum\ScopeEnum;
use app\lib\exception\ThemeException;
use app\lib\exception\WeChatException;
use think\Exception;

class UserToken extends Token
{
    protected $code;
    protected $WeChat_AppID;
    protected $WeChat_Secret;
    protected $WeChat_LoginUrl;

    function __construct($code)
    {
        $this->code = $code;
        $this->WeChat_AppID = config('WeChat.app_id');
        $this->WeChat_Secret = config('WeChat.app_secret');

        $this->WeChat_LoginUrl = sprintf(config('WeChat.login_url'), $this->WeChat_AppID, $this->WeChat_Secret, $this->code);
    }

    public function get()
    {
        $result = curl_get($this->WeChat_LoginUrl);
        $wxResult = json_decode($result, true);

        if (empty($wxResult)) {
            throw new Exception('获取session_key及openID时异常,微信内部错误');
        } else {
            $loginFail = array_key_exists('errcode', $wxResult);
            if ($loginFail) {
                $this->processLoginError($wxResult);
            } else {
                return $this->grantToken($wxResult);
            }

        }
    }

    private function grantToken($wxResult)
    {
        //拿到openid
        $openid = $wxResult['openid'];
        //查看数据库
        $user = UserModel::getByOpenID($openid);
        if ($user) {
            $uid = $user->id;
        } else {
            $uid = $this->newUser($openid);
        }
        // 生成令牌
        //key:令牌 value:$wxResult uid scope
        $cachedValue = $this->prepareCachedValue($wxResult, $uid);
        $token = $this->saveToCache($cachedValue);

        return $token;
    }

    private function saveToCache($cacheValue)
    {
        $key = self::generateToken();
        $value = json_encode($cacheValue);
        $expire_in = config('setting.token_expire_in');
        //此处可以替换成缓存
        $request = cache($key, $value, $expire_in);
        if (!$request) {
            throw new ThemeException([
                'msg' => '服务器缓存异常',
                'errorCode' => 10005
            ]);
        }
        return $key;
    }

    private function prepareCachedValue($wxResult, $uid)
    {
        $cachedValue = $wxResult;
        $cachedValue['uid'] = $uid;
        $cachedValue['scope'] = ScopeEnum::User; ///作用域代表App用户的权限
        return $cachedValue;
    }

    private function newUser($openid)
    {
        $user = UserModel::create([
            'openid' => $openid,
        ]);
        return $user->id;
    }

    private function processLoginError($wxResult)
    {
        throw new WeChatException([
            'msg' => $wxResult['errmsg'],
            'errorCode' => $wxResult['errcode']
        ]);

    }
}